﻿namespace FFF.Test.Application.DomainServices.FW
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    using Abp.Domain.Services;
    using Abp.Domain.Uow;
    using Abp.EntityFrameworkCore.Uow;
    using Abp.EntityFrameworkCore;
    using AutoMapper;
    using Abp.UI;
    using Ydm.Helper;
    using Ydm.Extensions;
    using Microsoft.EntityFrameworkCore;
    using AutoMapper.QueryableExtensions;
    using FFF.Test.DataAccess.Framework;
    using FFF.Test.Application.Repositories.FW;
    using FFF.Test.Entity.FW;
    using FFF.Test.Entity.FW.Dto;
    using FFF.Test.Entity.FW.View;
    using Ydm.QueryFilter.Core;

    /// <summary>
    /// 标准角色动作中间表领域层服务接口
    /// </summary>
    public class FWStandardRole2ActionDomainService : YdmAbpDomainServiceBase, IFWStandardRole2ActionDomainService
    {
        /// <summary>
        /// 标准角色动作中间表仓储
        /// </summary>
        private readonly IFWStandardRole2ActionRepository _fWStandardRole2ActionRepository;

        private readonly IFWModuleRepository _fWModuleRepository;
        private readonly IFWFunctionRepository _fWFunctionRepository;
        private readonly IFWActionRepository _fWActionRepository;
        private readonly IFWApplication2ModuleRepository _fWApplication2ModuleRepository;
        private readonly IFWCompany2ActionRepository _fWCompany2ActionRepository;

        /// <summary>
        /// Initializes a new instance of the <see cref="FWStandardRole2ActionDomainService"/> class.
        /// 标准角色动作中间表领域层操作
        /// </summary>
        /// <param name="fWStandardRole2ActionRepository">标准角色动作中间表仓储</param>
        /// <param name="fWModuleRepository">模块仓储</param>
        /// <param name="fWFunctionRepository">菜单仓储</param>
        /// <param name="fWActionRepository">动作点仓储</param>
        /// <param name="fWApplication2ModuleRepository">系统仓储中间表</param>
        /// <param name="fWCompany2ActionRepository">fwcompany中间表</param>
        public FWStandardRole2ActionDomainService(
            IFWStandardRole2ActionRepository fWStandardRole2ActionRepository,
            IFWModuleRepository fWModuleRepository,
            IFWFunctionRepository fWFunctionRepository,
            IFWActionRepository fWActionRepository,
            IFWApplication2ModuleRepository fWApplication2ModuleRepository,
            IFWCompany2ActionRepository fWCompany2ActionRepository
        )
        {
            this._fWStandardRole2ActionRepository = fWStandardRole2ActionRepository;
            this._fWModuleRepository = fWModuleRepository;
            this._fWFunctionRepository = fWFunctionRepository;
            this._fWActionRepository = fWActionRepository;
            this._fWApplication2ModuleRepository = fWApplication2ModuleRepository;
            this._fWCompany2ActionRepository = fWCompany2ActionRepository;
        }

        /// <summary>
        /// 1.008 批量保存角色的权限(于大明)
        /// </summary>
        /// <param name="inDto">批量保存角色的权限输入dto</param>
        /// <returns>批量保存角色的权限输出dto</returns>
        public async Task<BatchSaveRoleActionOutDto> BatchSaveRoleActionAsync(BatchSaveRoleActionInDto inDto)
        {
            var viewStandRole = this._fWStandardRole2ActionRepository.GetView();
            var result = new BatchSaveRoleActionOutDto();

            // 先删除
            var guids = await viewStandRole.Where(x => x.StandardRoleGUID == inDto.StandardRoleGUID).Select(x => x.Id).ToListAsync();
            foreach (var id in guids)
            {
                await this._fWStandardRole2ActionRepository.DeleteByIdAsync(id);
            }

            // 如果有父级GUID那么也需要保存
            var entitys = inDto.ActionIds.Select(actionGUID => new FWStandardRole2ActionEntity()
            {
                Id = Guid.NewGuid(),
                ActionGUID = actionGUID,
                StandardRoleGUID = inDto.StandardRoleGUID,
                CreateTime = DateTime.Now
            });

            await this._fWStandardRole2ActionRepository.GetDbContext().BulkInsertAsync(entitys);

            return result;
        }

        /// <summary>
        /// 1.007 获取角色的权限(于大明)
        /// </summary>
        /// <param name="inDto">获取角色的权限输入dto</param>
        /// <returns>获取角色的权限输出dto</returns>
        public async Task<GetRoleRightsOutDto> GetRoleRightsAsync(GetRoleRightsInDto inDto)
        {
            var viewModule = this._fWModuleRepository.GetView();
            var viewFunction = this._fWFunctionRepository.GetView();
            var viewAction = this._fWActionRepository.GetView();

            var viewRole2Action = this._fWStandardRole2ActionRepository.GetView();
            var fwApp2ModuleQuery = this._fWApplication2ModuleRepository.GetView();
            var c2buQuery = this._fWCompany2ActionRepository.GetView();

            if (inDto.IsBuSet == 1)
            {
                viewAction = viewAction.AsNoFilter();
                fwApp2ModuleQuery = fwApp2ModuleQuery.AsNoFilter();
                viewFunction = viewFunction.AsNoFilter();
            }

            var result = new GetRoleRightsOutDto();
            result.ModuleDtos = await fwApp2ModuleQuery
                .Where(x => x.ApplicationGUID == inDto.ApplicationGUID && x.ModuleIsDisable == 0 && (string.IsNullOrEmpty(x.ModuleUrl) || x.IsFullModule == 1))
                .OrderBy(x => x.A2MOrderCode)
                .ThenBy(x => x.CreateTime)
                .Select(x => new GetRoleRightsModuleDto
                {
                    ModuleGUID = x.Id,
                    ModuleName = x.ModuleName,
                    FunctionDtos = viewFunction
                   .Where(y => y.ModuleGUID == x.ModuleGUID && !viewFunction.Any(k => k.ParentGUID == y.Id))
                   .OrderBy(y => y.FullCode)
                   .ThenBy(y => y.CreateTime)
                   .Select(y => new GetRoleRightsFunctionDto
                   {
                       FunctionName = y.FunctionName,
                       FunctionGUID = y.Id,
                       ParentFunctionName = y.ParentFunctionName,
                       ParentGUID = y.ParentGUID,
                       ActionDtos = viewAction.Where(z => z.FunctionGUID == y.Id)
                       .OrderBy(z => z.ActionCode)
                       .Select(z => new GetRoleRightsActionDto
                       {
                           ActionGUID = z.Id,
                           ActionName = z.ActionName,
                           IsChecked = inDto.IsBuSet == 0 ? viewRole2Action.Where(m => m.StandardRoleGUID == inDto.RoleGUID).Any(m => m.ActionGUID == z.Id) : c2buQuery.Where(m => m.CompanyGUID == inDto.RoleGUID).Any(m => m.ActionGUID == z.Id)
                       }).ToList()
                   }).ToList()
                }).ToListAsync();
            return result;
        }
    }
}
